﻿using GN.Pay.Utils;
using GN.Pay.Utils.Security;
using System;
using System.Collections.Generic;
using System.Web;

namespace GN.Pay.TradeChannel.UnionPay.Request
{
    [Serializable]
    abstract class APayRequest : AService
    {
        /// <summary>
        /// 版本号 version   必填    固定填写5.1.0 
        /// </summary>
        public string version { get; set; }

        /// <summary>
        /// 编码方式 encoding 必填 默认取值：UTF-8 
        /// </summary>
        public string encoding { get; set; }

        /// <summary>
        /// 证书ID certId 必填 
        /// </summary>
        public string certId { get; set; }

        /// <summary>
        /// 签名方法 signMethod  必填 非对称签名： 01（表示采用RSA签名） HASH表示散列算法 11：支持散列方式验证SHA-256 12：支持散列方式验证SM3  
        /// </summary>
        public string signMethod { get; set; }

        /// <summary>
        /// 交易类型 txnType 必填 取值：01 
        /// </summary>
        public string txnType { get; set; }

        /// <summary>
        /// 交易子类 txnSubType 必填 01：自助消费，通过地址的方式区分前台消费和后台消费（含无跳转支付）03：分期付款 
        /// </summary>
        public string txnSubType { get; set; }

        /// <summary>
        /// 产品类型 bizType 
        /// </summary>
        public string bizType { get; set; }

        /// <summary>
        /// 渠道类型
        /// </summary>
        public string channelType { get; set; }

        /// <summary>
        /// 签名 signature ANS1..1024 M 填写对报文摘要的签名，可通过SDK生成签名 
        /// </summary>
        public string signature { get; set; }

        /// <summary>
        /// 前台通知地址
        /// </summary>
        public string frontUrl { get; set; }

        /// <summary>
        /// 后台通知地址
        /// </summary>
        public string backUrl { get; set; }

        /// <summary>
        /// 接入类型 accessType 必填  0：普通商户直连接入 2：平台类商户接入 
        /// </summary>
        public string accessType { get; set; }

        /// <summary>
        /// 商户代码
        /// </summary>
        public string merId { get; set; }

        /// <summary>
        /// 加密证书ID encryptCertId C 
        /// </summary>
        public string encryptCertId { get; set; }

        /// <summary>
        /// 账号类型   后台类交易且卡号上送；跨行收单且收单机构收集银行卡信息时上送 01：银行卡 02：存折 03：IC卡 默认取值：01 取值“03”表示以IC终端发起的IC卡交易，IC作为普通银行卡进行支付时，此域填写为“01” 
        /// </summary>
        public string accType { get; set; }        

        public SignDictionary BuildSignDictionary(IChannel channel,
            UnionPayConfigure config,
            params string[] removeKeys)
        {
            this.certId = config.ConfigureInfo.GetSignCertId();
            var dic = this.GetSignDictionary(StringComparer.Ordinal);
            SortedDictionary<string, string> removeDic = new SortedDictionary<string, string>();
            if (removeKeys != null)
            {
                foreach (var key in removeKeys)
                {
                    string replaceValue = "";
                    if (key != null && dic.TryGetValue(key, out replaceValue))
                    {
                        dic.Remove(key);
                        removeDic[key] = replaceValue;
                    }
                }
            }
            string content = dic.UrlLinkString(null, null);
            if (string.IsNullOrWhiteSpace(content))
            {
                channel.ThrowChannelValidationException("待签名内容为null或空白字符");
            }
            this.signature = SecurityUtils.Sign(config.ConfigureInfo, content);
            if (removeDic.Count > 0)
            {
                foreach (var item in removeDic)
                {
                    dic[item.Key] = item.Value;
                }
            }
            dic["signature"] = signature;
            return dic;
        }



        /// <summary>
        /// 生成签名参数
        /// </summary>
        /// <param name="removeKeys">需移除的参数，即不能参与签名的参数</param>
        /// <returns></returns>
        protected string BuildSignUrlLinkParam(ITradeChannel channel,
            UnionPayConfigure config, params string[] removeKeys)
        {
            var dic = this.BuildSignDictionary(channel, config, removeKeys);
            var param = dic.UrlLinkString(null, null);
            dic.Clear();
            return param;
        }
    }
}
